package com.wikidot.designpatterns.abstractfactory.example2;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;

public class TireVendorFactory implements TireVendor {
	private static String PATH = "bin/com/wikidot/designpatterns/abstractfactory/example2/factory.properties";
	private Map<String, TireVendor> factories;

	public TireVendorFactory() {
		loadFactories();
	}

	private void registerFactory(String brand, String className) {
		Class<TireVendor> clazz;
		TireVendor instance;
		try {
			clazz = (Class<TireVendor>) Class.forName(className);

			if (!TireVendor.class.isAssignableFrom(clazz)) {
				System.out.println(" - required interface not implemented.");
			} else {
				instance = clazz.newInstance();
				this.factories.put(brand, instance);
				System.out.println(" - successfuly registered.\n");
			}
		} catch (ClassNotFoundException e) {
			System.out.println(" - required class not found.");
		} catch (InstantiationException e) {
			System.out.println(" - required class cannot be instantiated.");
		} catch (IllegalAccessException e) {
			System.out.println(" - required class cannot be instantiated.");
		}
	}

	private void loadFactories() {
		Properties p = new Properties();
		this.factories = new HashMap<String, TireVendor>();
		try {
			p.load(new FileInputStream(PATH));
			Iterable<Entry<Object, Object>> entrySet = p.entrySet();
			String brand, className;

			for (Entry<Object, Object> entry : entrySet) {
				String key = (String) entry.getKey();
				if (key.startsWith("brand") && !key.endsWith("class")) {
					brand = (String) entry.getValue();
					className = p.getProperty(key + ".class");

					System.out.print("Brand found: " + brand);

					registerFactory(brand, className);

				}
			}
		} catch (FileNotFoundException e) {
			throw new IllegalArgumentException("Property file not found.");
		} catch (IOException e) {
			throw new RuntimeException("Accessing file failed.");
		}
	}

	public TireVendor getTireFactory(String brand) {

		return factories.get(brand);
	}

	@Override
	public Tire produceTire() {
		// TODO Auto-generated method stub
		return null;
	}

	public static void main(String[] args) {
		TireVendorFactory k = new TireVendorFactory();
		TireVendor kk = k.getTireFactory("michelin");
		System.out.println(kk.produceTire());
	}
}
